﻿//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Microsoft Public License.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace AstoriaOverAstoria
{
    using System.Collections;
    using System.Collections.Generic;

    /// <summary>Special implementation of the <see cref="IQueryResultsProcessor"/>
    /// which allows chaining of the query results processors.</summary>
    internal class CombiningQueryResultsProcessor : IQueryResultsProcessor
    {
        /// <summary>The list (ordered) of query results processors to apply.</summary>
        private List<IQueryResultsProcessor> queryResultsProcessors = new List<IQueryResultsProcessor>();

        /// <summary>Adds a new <paramref name="processor"/> to the end of the list of processors to apply.</summary>
        /// <param name="processor">The processor to add.</param>
        public void AddProcessor(IQueryResultsProcessor processor)
        {
            this.queryResultsProcessors.Add(processor);
        }

        /// <summary>Method which processes a single result of a query before it is handed to the server.</summary>
        /// <param name="result">The result produced by the query (and any result processors) so far.</param>
        /// <param name="context">The context which is executing the query.</param>
        /// <returns>The result of the query after the transformation.</returns>
        public object ProcessSingleResult(object result, AstoriaOverAstoriaContext context)
        {
            foreach (var processor in this.queryResultsProcessors)
            {
                result = processor.ProcessSingleResult(result, context);
            }

            return result;
        }

        /// <summary>Processes the results. This applies all the processed one by one passing the result of the previous one
        /// to the next one in the other the processors where added.</summary>
        /// <param name="results">The results to be processed.</param>
        /// <param name="context">The context which is executing the query.</param>
        /// <returns>The processed results.</returns>
        public IEnumerable ProcessResults(IEnumerable results, AstoriaOverAstoriaContext context)
        {
            foreach (var processor in this.queryResultsProcessors)
            {
                results = processor.ProcessResults(results, context);
            }

            return results;
        }
    }
}
